﻿using Caliburn.Micro;
using LiveChartsCore.SkiaSharpView;
using MCPlatform.Builder.WorkStation.StationEvents;
using MCPlatform.Builder.WorkStation.StationEvents.Cutting;
using MCPlatform.Builder.WorkStation.StationEvents.Load;
using MCPlatform.Builder.WorkStation.StationEvents.Unload;
using MCPlatform.Communicate.SerialPorts;
using MCPlatform.Communicate.TcpIp;
using MCPlatform.Components.Utilities;
using MCPlatform.Dxf.Entities;
using MCPlatform.Dxf.Readers;
using MCPlatform.Dxf.Utils;
using MCPlatform.Dxf.Views;
using MCPlatform.Models;
using MCPlatform.MotionLib.Base;
using MCPlatform.MotionLib.Base.AssitantClass;
using MCPlatform.MotionLib.Base.Environment;
using MCPlatform.Shared.Enums;
using MCPlatform.UI.Controls.Models;
using MCPlatform.UI.Controls.Views;
using MCPlatform.UI.Controls.Views.MotionControl;
using MCPlatform.ViewModels;
using MCPlatform.ViewModels.Product;
using netDxf;
using Panuon.WPF.UI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;

namespace MCPlatform.Builder.WorkStation
{
    public class CuttingStation : WorkStationBase,IHandle<LoadToCuttingEvent>,IHandle<UnloadToCuttingEvent>
    {
        #region Properties

        public static NTcpClient? NTcpClient { get; set; }

     
        public IMotion XAxis { get; set; }

        public IMotion YAxis { get; set; }
        public IMotion ZAxis { get; set; }
   
        public IMotion UAxis { get; set; }


        public IImputation Cordinate { get; set; }
        public PointSettingModel XWaitPos { get; set; }

        public PointSettingModel YWaitPos { get; set; }
        public PointSettingModel ZWaitPos { get; set; }
        public PointSettingModel UWaitPos { get; set; }

      //  public PointSettingModel XPlacePos { get; set; }

      //  public PointSettingModel YCuttingCollcectPos { get; set; }

       // public PointSettingModel XCuttingPos { get; set; }

      //  public PointSettingModel YCuttingPos { get; set; }


       // public PointSettingModel XPhotoPos { get; set; }

      //  public PointSettingModel YPhotoPos { get; set; }


        public PointSettingModel ZCuttingPos { get; set; }


      //  public PointSettingModel XCollectPos { get; set; }

        public PointSettingModel CollectMotorTimes { get; set; }


      //  public PointSettingModel XLoadPos { get; set; }

       // public PointSettingModel XDividePos { get; set; }

     //   public PointSettingModel YDivideEndPos { get; set; }

     //   public PointSettingModel XSuckCollectDutPos { get; set; }

        public PointSettingModel PressVacummSuckTime { get; set; }

        public PointSettingModel XAxisReleaseDutBackwardDis { get; set; }


        public PointSettingModel ZAxisCuttingDelayTime { get; set; }

        public PointSettingModel XAxisLoadVel { get; set; }

        public IValve PressVacuum { get; set; }

        public IValve TransportValve { get; set; }

        public IValve PressValve { get; set; }

        public IValve FingerValve { get; set; }

        public IValve PunchValve { get; set; }

        public IValve CollectValve { get; set; }

        public IValve OprationVacuum { get; set; }

        public IValve OprationVacuum2 { get; set; }

        // public IIO HaveDutSensor { get; set; }

        public IIO CameraLight { get; set; }

        public IIO CuttingMotor { get; set; }

        public IIO PunchMotor { get; set; }

        public IIO CollectMotor { get; set; }



        public  Dictionary<Type, List<PathEntityBase>> EntitiesWithPaths = DxfView.EntitiesWithPaths;

        public ProductModel ProductModel { get; set; } = ProductInfo.GetProductInfo() ?? new ProductModel();

        #endregion

        #region Fields
        // bool isRunning =false ;

        bool _hasBeenLoad = false;
        bool _isFirstTimeLoad = true;

        private readonly double xPCuttingUAxisAngle = 0;
        private readonly double xNCuttingUAxisAngle = -180;
        private readonly double yPCuttingUAxisAngle =-90;
        private readonly double yNCuttingUAxisAngle = -270;


        // 初始化变量
        //double x = 0;
        //double y = 0;
        //double prevX = 0;
        //double prevY = 0;
        //double uAngle = 0; // 初始U轴角度为0度

        //视觉偏差
        bool _hasOffset = false;
        double _xVisionOffset = 0;
        double _yVisionOffset = 0;
        double _angleVisionOffset = 0;
      

        #endregion

        #region Events

        public event System.Action? ClearDoneEvent;

        public event System.Action<bool>? SingleCycleDoneEvent;
        #endregion

        #region CTOR
        private static CuttingStation? instance;
        private static readonly object lockObject = new object();

       

        public static CuttingStation Instance
        {
            get
            {
                lock (lockObject)
                {
                    if (instance == null)
                    {
                        instance = new CuttingStation();
                    }
                    return instance;
                }
            }
        }

      

        private CuttingStation()
        {
            WorkStationModel = WorkStation.Instance.WorkStationDic[2];

         


            XAxis = AxisModels[0].MotionEntity!;
            YAxis = AxisModels[1].MotionEntity!;
            ZAxis = AxisModels[2].MotionEntity!;
            UAxis = AxisModels[3].MotionEntity!;

            Cordinate = CoordinateModels[0].ImputationEntity!;

            PressVacuum = CylinderModels[0].ValveEntity!;

            TransportValve = CylinderModels[1].ValveEntity!;

            FingerValve = CylinderModels[2].ValveEntity!;

            PressValve = CylinderModels[3].ValveEntity!;

            PunchValve = CylinderModels[4].ValveEntity!;

            CollectValve = CylinderModels[5].ValveEntity!;

            OprationVacuum = CylinderModels[6].ValveEntity!;

            OprationVacuum2 = CylinderModels[8].ValveEntity!;


            XWaitPos = PointSettingModels[0];
            YWaitPos = PointSettingModels[1];
            ZWaitPos = PointSettingModels[2];
            UWaitPos = PointSettingModels[3];
           // XPlacePos = PointSettingModels[4];
            //YCuttingCollcectPos = PointSettingModels[5];
            ZCuttingPos = PointSettingModels[4];
          

          //os = PointSettingModels[7];

            CollectMotorTimes = PointSettingModels[5];

            //XCuttingPos = PointSettingModels[9];
           // YCuttingPos = PointSettingModels[10];
            //XPhotoPos = PointSettingModels[11];
           // YPhotoPos = PointSettingModels[12];

            //XLoadPos = PointSettingModels[13];

            //XDividePos = PointSettingModels[14];

           // YDivideEndPos = PointSettingModels[15];

            //XSuckCollectDutPos = PointSettingModels[16];

            PressVacummSuckTime = PointSettingModels[6];

            XAxisReleaseDutBackwardDis = PointSettingModels[7];

            ZAxisCuttingDelayTime = PointSettingModels[8];

            XAxisLoadVel= PointSettingModels[9];

            PunchMotor =  IOModels[2].IOEntity!;

            CuttingMotor = IOModels[3].IOEntity!;

           

            CollectMotor = IOModels[5].IOEntity!;

          //  HaveDutSensor = IOModels[7].IOEntity;

            CameraLight = IOModels[6].IOEntity!;

          



        }


        public override void RegisterEvent()
        {
            ProductViewModel.SaveEvent += ProductViewModel_SaveEvent;
        }

        private void ProductViewModel_SaveEvent(ProductModel model)
        {
            ProductModel = model;
        }



        #endregion

        #region Methods

        public override async Task<bool> IsSaftyToMove()
        {
            await Task.Delay(1);
            return true;
        }


        public override async Task Initial()
        {
            try
            {
              
                await ResetSignal();


                await Task.Run(async () =>
                {
                    //1.全部轴使能
                    SetAllAxisEnable();

                    //2.全部气缸回原位
                    await SetAllValvesBasing();

                    //3.电机回原
                    //3.轴回原
                    await HomeAsync(ZAxis);
                    await HomeAsync(UAxis);                    
                    await HomeAsync(XAxis);
                    await HomeAsync(YAxis);

                    await AbsMoveAsync(UAxis, new PointSettingModel() { Parameter = 0});
                    await AbsMoveAsync(ZAxis, ZWaitPos);
                    await AbsMoveAsync(YAxis, YWaitPos);
                    await AbsMoveAsync(XAxis, XWaitPos);

                    LogModel.LogInfo = "初始化完成！";
                    LogModel.Status = Shared.Enums.WorkStationStatus.Idle;
                   
                }, cancellationToken);
            }
            catch (Exception)
            {
               
                throw;
            }
          
           
        }

        public override async Task DryRun()
        {       
            try
            {
                await CheckStationStatus();

               

                if (!ProductModel.IsPhoto && !ProductModel.IsPunch)
                {
                    await CutttingAllPiese();
                }
                else
                {
                    for (int i = 0; i < ProductModel.CuttingProductNumberOneTime; i++)
                    {
                        await CuttingOnePiece(i);
                    }
                }


                //2.操作台吸盘松开
                await BasingAsync(OprationVacuum);
                await BasingAsync(OprationVacuum2);

                //去等待位
                await AbsMoveAsync(XAxis,XWaitPos);

                DoneEventTrigger(this, new CuttingToUnloadEvent() { MessageType = MessageType.NotifyDone });


            }
            catch (Exception)
            {

                throw;
            }
        
     
        }

        public override Task Clear(bool isClear)
        {
            if (_isFirstTimeLoad == false && isClear)
            {
                _isFirstTimeLoad = true;
            }
            else if (_hasBeenLoad && !isClear)
            {
                _isFirstTimeLoad = false;
            }

            return Task.CompletedTask;
        }
        public override async Task Test()
        {

            //await CuttingOnePiece();

            //await CuttingOnePiece(1);

            //await CuttingOnePiece(2);
            Send(new CuttingToLoadEvent() { MessageType=MessageType.NotifyDone});


        }

        public override async Task Execute()
        {
            await Task.Delay(1000);
        }

        public override Task ResetSignal()
        {           
            PauseEventSource.Set();
            _isFirstTimeLoad = true;
            SingleStepCompleteEvent.Set();
            //  isRunning = false;
            //XAxis.SetGearFollow(4, false);
            //XAxis.SetGrantError(false, 1, 1);
            return Task.CompletedTask;
        }

        public override void StationStop()
        {
            CollectMotor.Value = false;
            PunchMotor.Value = false;
            CuttingMotor.Value = false;
        }


        public  void NextCycle()
        {
             Send(new CuttingToLoadEvent() { MessageType = MessageType.NotifyDone });
        }

        #endregion


        #region Event Handler

        /// <summary>
        /// 上料给切割工站信息
        /// </summary>
        /// <param name="message"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task HandleAsync(LoadToCuttingEvent message, CancellationToken cancellationToken)
        {
            try
            {
                if (IsReadyNotify(message))
                {
                    Send(new CuttingToLoadEvent() { MessageType=MessageType.ResetReady});
                    await Task.Run(async() =>
                    {
                        await LoadDutAsync();
                        await DryRun();
                    });
                    
                }
            }
            catch (Exception e)
            {
                Logger.Error(e,e.Message);
                StopTrigger();
              //  StopTrigger();
                //MessageBox.Show(e.Message);
                return;
               // throw;
            }
           
        }


        /// <summary>
        /// 下料给切割工站信息
        /// </summary>
        /// <param name="message"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task HandleAsync(UnloadToCuttingEvent message, CancellationToken cancellationToken)
        {
            try
            {

                
                if (IsDoneNotify(message))
                {
                  
                    Send(new CuttingToUnloadEvent() { MessageType = MessageType.ResetDone });
                    await Task.Run(async () =>
                    {
                        await CollectDutAsync();
                    });

                    
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                return;
                //throw;
            }
          
           
        }



        #endregion


        #region Actions

        private async Task CutttingAllPiese()
        {
            try
            {
                //1.去开始切料位置            
                await MultiAbsMoveAsync(new IMotion[] { XAxis, YAxis, UAxis }, new PointSettingModel() { Parameter = ProductModel.StartCuttingXPos }, new PointSettingModel() { Parameter = ProductModel.StartCuttingYPos }, new PointSettingModel() { Parameter = 0 });
                //2.开始X轴切割
                PointSettingModel xPCuttingLength =new PointSettingModel() {ControlName="切割X轴正向切割长度" ,Parameter=  (ProductModel.CuttingLength  ) * ProductModel.CuttingProductNumberOneTime + ProductModel.KnifeCompensate + ProductModel.XAxisFirstCompensate };
                PointSettingModel xNCuttingLength = new PointSettingModel() { ControlName = "切割X轴负向切割长度", Parameter = (ProductModel.CuttingLength  * ProductModel.CuttingProductNumberOneTime + ProductModel.KnifeCompensate + ProductModel.XAxisFirstCompensate) * -1 };
                PointSettingModel yPCuttingLength = new PointSettingModel() { ControlName = "切割Y轴正向切割长度", Parameter = ProductModel.CuttingWidth + ProductModel.KnifeCompensate };
                PointSettingModel yNCuttingLength = new PointSettingModel() { ControlName = "切割Y轴负向切割长度", Parameter = (ProductModel.CuttingWidth  + ProductModel.KnifeCompensate)*-1 };
                //3.X正向切割
                await AxisCuttingAsync(XAxis, xPCuttingLength, xPCuttingUAxisAngle);

                //4.Y正向切割
              
                await AxisCuttingAsync(YAxis, yPCuttingLength, yPCuttingUAxisAngle);

                //5.X往负方向切割
                await AxisCuttingAsync(XAxis, xNCuttingLength, xNCuttingUAxisAngle);

                //6.Y负向切割

                await AxisCuttingAsync(YAxis, yNCuttingLength, yNCuttingUAxisAngle);

                //7.Y轴切割开始位置
                for (int i = 1; i < ProductModel.CuttingProductNumberOneTime; i++)
                {
                    await YAxisCutting(i);
                }


            }
            catch (Exception)
            {

                throw;
            }
        }

        private async Task YAxisCutting(int times = 1)
        {
            try
            {
                PointSettingModel yPCuttingLength = new PointSettingModel() { ControlName = "切割Y轴正向切割长度", Parameter = ProductModel.CuttingWidth + ProductModel.KnifeCompensate };
                PointSettingModel xPCuttingLengthPos = new PointSettingModel() { ControlName = $"切割X轴第{times+1}块开始位置", Parameter = ProductModel.StartCuttingXPos+ ProductModel.XAxisFirstCompensate + ProductModel.KnifeCompensate + (ProductModel.CuttingLength  * times) };


                await MultiAbsMoveAsync(new IMotion[] { XAxis, YAxis, UAxis }, xPCuttingLengthPos, new PointSettingModel() { Parameter = ProductModel.StartCuttingYPos }, new PointSettingModel() {ControlName="切割U轴原位", Parameter = yPCuttingUAxisAngle });
                //8.Y正向切割

                await AxisCuttingAsync(YAxis, yPCuttingLength, yPCuttingUAxisAngle);
            }
            catch (Exception)
            {

                throw;
            }
        }

        private async Task CuttingOnePiece(int times = 0)
        {
            try
            {
                //0.判断是否需要切第四刀
                bool isNeed4Cutting = true;

                if (times > 0)
                {
                    isNeed4Cutting = false;
                }
                //1.判断是否需要拍照
                if (ProductModel.IsPhoto)
                {
                    await ToPhotoPos(times);
                }

                //2.是否需要打孔
                if (ProductModel.IsPunch)
                {
                    await ToPunch();
                }




                //3.切料
                if (ProductModel.IsPhoto)
                {
                    await CoordCuttingRectangleAsync(times);
                }
                else
                {
                    await XYCuttingRectangelAsync(times, isNeed4Cutting);
                }
               
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 常规切料
        /// </summary>
        /// <param name="times">次数</param>
        /// <param name="isNeed4Cutting">是否要切第四刀</param>
        /// <returns></returns>
        private async Task XYCuttingRectangelAsync(int times = 0, bool isNeed4Cutting = true)
        {
            try
            {
               

              
                //1.获取切料位
               // (PointSettingModel startXPos, PointSettingModel startYPos, PointSettingModel startZPos) = ProductInfo.GetCuttingStartPos();

                //(PointSettingModel pXCuttingLenght,
                //   PointSettingModel pYCuttingWidth,
                //   PointSettingModel nXCuttingLenght,
                //   PointSettingModel nYCuttingWidth,
                //   PointSettingModel sp
                //   )
                //   cuttingInfo = ProductInfo.GetCuttingLengthAndWidth();

                //2.判断是第几次切割，要移动相应的距离
                double xMoveDistence = times * (ProductModel.Space + ProductModel.CuttingLength+ProductModel.KnifeCompensate);

                PointSettingModel newStartXPos = new PointSettingModel() { Parameter = ProductModel.StartCuttingXPos + xMoveDistence };

                PointSettingModel uAxisHomePos = new PointSettingModel() { Parameter = 0 };

                await MultiAbsMoveAsync(new IMotion[] { XAxis, YAxis, UAxis }, newStartXPos, new PointSettingModel() { Parameter= ProductModel.StartCuttingYPos }  , uAxisHomePos);

                //3.开始切割
                if (ProductModel.Space == 0 && times > 0)
                {
                    isNeed4Cutting = false;
                }
                await CuttingRectangelAsync(isNeed4Cutting: isNeed4Cutting);
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 去拍照位
        /// </summary>
        /// <returns></returns>
        private async Task ToPhotoPos(int times = 0)
        {
            try
            {
               // (PointSettingModel xPos,PointSettingModel yPos) = ProductInfo.GetPhotoPos();

               // double space = ProductInfo.GetPatternSpace();

                PointSettingModel newPhotoXPos = new PointSettingModel() { Parameter = ProductModel.XAxisPhotoPos  + ProductModel.Space };

               // double newXPhotoPos = ProductModel.XAxisPhotoPos + ProductModel.Space;

                await MultiAbsMoveAsync(new IMotion[] { XAxis, YAxis }, newPhotoXPos, new PointSettingModel() { ControlName = "切割Y轴拍照位置",Parameter = ProductModel.YAxisPhotoPos });
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 去打孔位
        /// </summary>
        /// <returns></returns>
        private async Task ToPunch()
        {
            try
            {
                (bool hasOffset,double xPos, double yPos, double zPos) = await GetVisionOffset();
                

                if (hasOffset)
                {
                    await PunchAllAsync(xPos, yPos);
                }
            }
            catch (Exception)
            {

                throw;
            }
        }


        /// <summary>
        /// 搬运物料逻辑
        /// </summary>
        /// <returns></returns>
        private async Task LoadDutAsync()
        {
            try
            {
                //1. X轴到取料位
                if (_isFirstTimeLoad)
                {
                   
                    await AbsMoveAsync(XAxis, XWaitPos);
                }
                else
                {
                    await AbsMoveAsync(XAxis, ProductModel.LoadXPos);
                }
               

                //2.气缸抓物料
                await GrapDutAsync();

                //   XAxis.SetVelocity(10);

                //var slaveAxisID = await Send(new CuttingToLoadEvent() { MessageType = MessageType.RequestAxisID});

                //龙门耦合主从轴
                //var res = XAxis.SetGearFollow(4,true);

                //res = XAxis.SetGrantError(true,1,1);

               var xAxisconfig =  XAxis.AxisConfig;
                var sTime = XAxis.AxisConfig.SPara;
                var velocity = XAxis.GetVelocity;
                // XAxis.ChangeVelocity(XAxisLoadVel.Parameter,);
                XAxis.AxisConfig.SPara = 0;
                XAxis.SetProfile();
                XAxis.SetVelocity(XAxisLoadVel.Parameter);
               

                if (_isFirstTimeLoad)
                {
                    _isFirstTimeLoad = false;
                    _hasBeenLoad = true;
                    ClearDoneEvent?.Invoke();
                     Send(new CuttingToLoadEvent() { MessageType = MessageType.NotifyDrag, Message = XAxis.GetVelocity, CustomMessage = ProductModel.ReleaseClampXPos - XWaitPos.Parameter });
                }
                else
                {
                     Send(new CuttingToLoadEvent() { MessageType = MessageType.NotifyDrag, Message = XAxis.GetVelocity, CustomMessage = ProductModel.ReleaseClampXPos - ProductModel.LoadXPos });
                }

               

                //3.X轴到放料位
                await AbsMoveAsync(XAxis, ProductModel.ReleaseClampXPos);

                Send(new CuttingToLoadEvent() { MessageType = MessageType.NotifyStopDrag });

                //变速回来

                XAxis.AxisConfig.SPara = sTime;
                XAxis.SetProfile();
                XAxis.ChangeVelocity(velocity, xAxisconfig.Acc);
                //解除龙门耦合
                //res = XAxis.SetGearFollow(4, false);

                //res = XAxis.SetGrantError(false, 1, 1);

               


               


                //4. 松开物料
                await BasingAsync(FingerValve);



                //6.打开光源
                if (ProductModel.IsPhoto)
                {
                    CameraLight.Value = true;
                }
               

                //7.搬运气缸缩回
                await BasingAsync(TransportValve);

                //8.松开物料后，X轴后移距离
                await RelMoveAsync(XAxis, XAxisReleaseDutBackwardDis);

                //5.操作台吸盘吸住
                await WorkingAsync(OprationVacuum);
                await WorkingAsync(OprationVacuum2);


                //9.切断
                await CuttOffAsync();

                ////8.XY轴过去分料
                //await MultiAbsMoveAsync(new IMotion[] { XAxis ,YAxis},new PointSettingModel() {ControlName="X轴切断位置", Parameter = ProductModel.CutOffXPos},YWaitPos);

                ////9.Z轴下去切割              
                //await AxisCuttingByAbsAsync(YAxis, new PointSettingModel() {ControlName="Y轴切断结束位置", Parameter=ProductModel.CutOffEndYPos}, yPCuttingUAxisAngle);

            }
            catch (Exception)
            {

                throw;
            }
        }


        /// <summary>
        /// 切断皮革
        /// </summary>
        /// <returns></returns>
        private async Task CuttOffAsync()
        {
            try
            {
                //1.XY轴过去分料
                await MultiAbsMoveAsync(new IMotion[] { XAxis, YAxis,UAxis },
                    new PointSettingModel() { ControlName = "X轴切断位置", Parameter = ProductModel.CutOffXPos }, 
                    new PointSettingModel() { ControlName = "Y轴切断位置", Parameter = ProductModel.CutOffYPos },
                    new PointSettingModel() { Parameter = yPCuttingUAxisAngle });

                //2.Z轴下去切割              
                await AxisCuttingByAbsAsync(YAxis, new PointSettingModel() { ControlName = "Y轴切断结束位置", Parameter = ProductModel.CutOffEndYPos }, yPCuttingUAxisAngle);

                //3.Y去开始切断点反向切割 
                await MultiAbsMoveAsync(new IMotion[] { YAxis, UAxis },                 
                   new PointSettingModel() { ControlName = "Y轴切断位置", Parameter = ProductModel.CutOffYPos+20 },
                   new PointSettingModel() { Parameter = yNCuttingUAxisAngle });

                //4.Z轴下去切割              
                await AxisCuttingByAbsAsync(YAxis, YWaitPos, yNCuttingUAxisAngle);

            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 抓取皮革产品
        /// </summary>
        /// <returns></returns>
        private async Task SuckDutAsync()
        {
            try
            {
                await BasingAsync(TransportValve);

                await BasingAsync(FingerValve);

                //1.下压气缸下压
                await WorkingAsync(PressValve);

                //2.真空吸
                await WorkingAsync(PressVacuum);

                await Task.Delay((int)PressVacummSuckTime.Parameter);

                //3.下压气缸升起
                await BasingAsync(PressValve);

                //4.搬运气缸伸出
                //await WorkingAsync(TransportValve);

                ////5.手指气缸夹
                //await WorkingAsync(FingerValve);

                //await Task.Delay(300);

                ////6.破真空
                //await BasingAsync(PressVacuum);

                //7.搬运气缸缩回
                //await BasingAsync(TransportValve);
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 抓取皮革产品
        /// </summary>
        /// <returns></returns>
        private async Task GrapDutAsync()
        {
            try
            {
                await BasingAsync(TransportValve);

                await BasingAsync(FingerValve);

                //1.下压气缸下压
                await WorkingAsync(PressValve);

                //2.真空吸
                await WorkingAsync(PressVacuum);

                

                await Task.Delay((int)PressVacummSuckTime.Parameter);

                //3.下压气缸升起
                await BasingAsync(PressValve);

                //4.搬运气缸伸出
                await WorkingAsync(TransportValve);

                //5.手指气缸夹
                await WorkingAsync(FingerValve);

                await Task.Delay(300);

                //6.破真空
                await BasingAsync(PressVacuum);

                //7.搬运气缸缩回
                //await BasingAsync(TransportValve);
            }
            catch (Exception)
            {

                throw;
            }
        }


        /// <summary>
        /// 回收物料逻辑
        /// </summary>
        /// <returns></returns>
        private async Task CollectDutAsync()
        {
            try
            {
                //0.Z抬刀
                await AbsMoveAsync(ZAxis,ZWaitPos);

                await BasingAsync(CollectValve);

                //1.X轴到吸废料位置
                await AbsMoveAsync(XAxis, ProductModel.CollectClampXPos);

                //2.抓取Dut
                await SuckDutAsync();

                //3.X轴往后拉到回收位置
                await AbsMoveAsync(XAxis,ProductModel.CollectReleaseXPos);

                //4.松开Dut
                await BasingAsync(PressVacuum);

                //await BasingAsync(TransportValve);

                //await BasingAsync(FingerValve);

                //List<Task> tasks = new List<Task>();

                //tasks.Add(DoubleCollectAsync());
                //tasks.Add( MultiAbsMoveAsync(new IMotion[] { XAxis, YAxis }, new PointSettingModel() { ControlName = "X轴上料位置", Parameter = ProductModel.LoadXPos }, YWaitPos));
                //await Task.WhenAll(tasks);

                //5.回收动作
                await DoubleCollectAsync();



                //7.XY轴过去分料位置
                await MultiAbsMoveAsync(new IMotion[] { XAxis, YAxis }, new PointSettingModel() {ControlName="X轴上料位置"  , Parameter = ProductModel.LoadXPos }   , YWaitPos);

                //8.发送回收废料完成给上料
                if (AutomaticSubMode is Shared.Enums.Modes.AutomaticSubMode.SingleCycle)
                {
                    var result = MessageBoxX.Show("单次循环完成！是否继续单次循环？","提示", MessageBoxButton.YesNo, MessageBoxIcon.Question, DefaultButton.YesOK);

                    if (result == MessageBoxResult.Yes)
                    {
                         Send(new CuttingToLoadEvent() { MessageType = MessageType.NotifyDone });
                        SingleCycleDoneEvent?.Invoke(false);
                    }
                    else
                    {
                        SingleCycleDoneEvent?.Invoke(true);
                    }


                    return;
                   
                }
                 Send(new CuttingToLoadEvent() { MessageType = MessageType.NotifyDone});

                //7.X轴到放料位
              //  await AbsMoveAsync(XAxis, XCuttingPos);

                //8.Y轴到切料位
              //  await AbsMoveAsync(YAxis, YCuttingPos);

                //9.Y轴负方向切割
               // await AxisCuttingAsync(YAxis, YWaitPos, yNCuttingUAxisAngle);
              
            }
            catch (Exception)
            {

                throw;
            }
        }


        private async Task CollectAsync()
        {
            try
            {
               
                //5.回收气缸夹住
                await WorkingAsync(CollectValve);

                await BasingAsync(CollectValve);

                await WorkingAsync(CollectValve);

                //6.调速电机调速固定时间
                CollectMotor.Value = true;

                await Task.Delay((int)CollectMotorTimes.Parameter);

                CollectMotor.Value = false;

                await BasingAsync(CollectValve);
            }
            catch (Exception)
            {

                throw;
            }
        }

        private async Task DoubleCollectAsync()
        {
            try
            {
                await Task.Delay(1000);
                //5.回收动作
                await CollectAsync();


                //6.回收动作
               // await CollectAsync();
            }
            catch (Exception)
            {

                throw;
            }
        }

        private async Task PunchAsync(double xPos,double yPos,double offsetX = 0, double offsetY = 0,double offsetZ=0)
        {
            try
            {
                //1.走打孔位置+偏移值
                IMotion[] motions = new IMotion[] { XAxis, YAxis,ZAxis };
                var points = DoubleToPoint(xPos + offsetX, yPos + offsetY, offsetZ);
                await MultiRelMoveAsync(motions, points);

                //2.开始打孔
                PunchMotor.Value = true;
                await WorkingAsync(PunchValve);


                //3.打孔收回
                await BasingAsync(PunchValve);
                PunchMotor.Value = false;

            }
            catch (Exception)
            {

                throw;
            }
        }

        private async Task<(bool,double,double,double)> GetVisionOffset()
        {
            if (NTcpClient!=null)
            {
                var res = await NTcpClient.WriteAndGetReply($"start,{XAxis.ActualPosition},{YAxis.ActualPosition}", TimeSpan.FromSeconds(10));
                var replys = res?.MessageString.Split(",");
                if (replys != null && replys.Length > 3)
                {
                    bool result = replys[0].Contains("1") ? true:false;
                    double xOffset = double.Parse(replys[1]);
                    double yOffset = double.Parse(replys[2]);
                    double angle = double.Parse(replys[3]);

                    _hasOffset = result;
                    _xVisionOffset = xOffset;
                    _yVisionOffset = yOffset;
                    _angleVisionOffset = angle;

                    return (result, xOffset, yOffset,angle);

                }
            }

            return (false,0,0,0);
          

        }

        private async Task PunchAllAsync(double offsetX = 0,double offsetY=0)
        {
            try
            {
                //1.先获取视觉点位和打孔点位
                var visionPoint = GetVisionPoint(EntitiesWithPaths);
                var punchPoints= GetPunchPoint(EntitiesWithPaths, visionPoint);

                if (punchPoints is null)
                {
                    return;
                }
                //2.读取打孔偏移值
                //(PointSettingModel punchXoffset, PointSettingModel punchYoffset, PointSettingModel punchZoffset)
                //    punchOffset = ProductInfo.GetPunchOffset();

                //3.先走偏移值
                IMotion[] motions = new IMotion[] { XAxis, YAxis,ZAxis };
                PointSettingModel punchXoffset = new PointSettingModel() { ControlName = "切割X轴打孔偏移", Parameter = ProductModel.PunchXOffset };
                PointSettingModel punchYoffset = new PointSettingModel() { ControlName = "切割Y轴打孔偏移", Parameter = ProductModel.PunchYOffset };
                PointSettingModel punchZoffset = new PointSettingModel() { ControlName = "切割Z轴打孔偏移", Parameter = ProductModel.PunchZOffset };
                var points = new PointSettingModel[] {  punchXoffset, punchYoffset, punchZoffset };
                await MultiRelMoveAsync(motions, points);

                bool first = false;

                //4.走全部点位
                foreach (var point in punchPoints)
                {
                    if (!first)
                    {
                        first = true;
                        await PunchAsync(point.X, point.Y, offsetX, offsetY);
                    }
                    else
                    {
                        await PunchAsync(point.X, point.Y);
                    }
                    
                }
               
            }
            catch (Exception)
            {

                throw;
            }
        }

        private async Task CuttingRectangelAsync(double offsetX = 0, double offsetY = 0, bool isNeed4Cutting = true)
        {
            try
            {
                //1.读取产品的信息
                (PointSettingModel pXCuttingLenght,
                    PointSettingModel pYCuttingWidth, 
                    PointSettingModel nXCuttingLenght,
                    PointSettingModel nYCuttingWidth,
                    PointSettingModel sp
                    ) 
                    cuttingInfo = GetCuttingLengthAndWidth();




                //1.1.先走偏移值
                IMotion[] motions = new IMotion[] { XAxis, YAxis };
                var points = DoubleToPoint(offsetX,offsetY);
                await MultiRelMoveAsync(motions, points);

                //2.X正向切割
                await AxisCuttingAsync(XAxis, cuttingInfo.pXCuttingLenght,xPCuttingUAxisAngle);
              


                //3.Y正向切割
                await AxisCuttingAsync(YAxis, cuttingInfo.pYCuttingWidth, yPCuttingUAxisAngle);

              

                //4.X往负方向切割
                await AxisCuttingAsync(XAxis, cuttingInfo.nXCuttingLenght, xNCuttingUAxisAngle);

                //5.判断是否需要切第4刀
                if (isNeed4Cutting)
                {
                    //6.Y往负方向切割
                    await AxisCuttingAsync(YAxis, cuttingInfo.nYCuttingWidth, yNCuttingUAxisAngle);
                }
               
               

                // await ImpRelMoveAsync(Cordinate, cuttingInfo.pXCuttingLenght, cuttingInfo.nYCuttingWidth);
                // Cordinate.ImpLineRelMove(new double[] { cuttingInfo.pXCuttingLenght .Parameter, cuttingInfo.nYCuttingWidth.Parameter});
              
                //7.XY去到下一个切割等待点              
              //  await MultiRelMoveAsync(new IMotion[] { XAxis ,UAxis }, cuttingInfo.pXCuttingLenght , new PointSettingModel() { Parameter = 180 });

              

            }
            catch (Exception)
            {

                throw;
            }
        }

        private async Task AxisCuttingAsync(IMotion axis,PointSettingModel cuttingLength,double knifeAngle)
        {
            try
            {
                //1.先抬刀
                await AbsMoveAsync(ZAxis, ZWaitPos);
                //2.旋转刀向
                await AbsMoveAsync(UAxis, new PointSettingModel() { Parameter = knifeAngle });
                //3.启动刀
                CuttingMotor.Value = true;
                //4.下刀
                await AbsMoveAsync(ZAxis, ZCuttingPos);
                await Task.Delay((int)ZAxisCuttingDelayTime.Parameter);
                //5.切割
                await RelMoveAsync(axis, cuttingLength);
                //6.停刀
                CuttingMotor.Value = false;
                //7.抬刀
                await AbsMoveAsync(ZAxis, ZWaitPos);
            }
            catch (Exception)
            {

                throw;
            }
        }

        private async Task CoordinateXCuttingAsync(PointSettingModel cuttingLength,double angle)
        {
            try
            {
                //0.计算坐标
                double xPos = Cordinate.XAxiPos + cuttingLength.Parameter;
                double yPos = Cordinate.YAxiPos ;
                
                //计算角度偏差后的XY目标值
                (double xTargetPos,double yTargetPos) = Components.Utilities.Utility.RotatePoint(xPos, yPos, angle); 

                //1.先抬刀
                await AbsMoveAsync(ZAxis, ZWaitPos);
                //2.旋转刀向
                double knifeAngle = Components.Utilities.Utility.CalculateAngle(Cordinate.XAxiPos, Cordinate.YAxiPos,xTargetPos,yTargetPos);
                await AbsMoveAsync(UAxis, new PointSettingModel() { Parameter = knifeAngle });
                //3.启动刀
                CuttingMotor.Value = true;
                //4.下刀
                await AbsMoveAsync(ZAxis, ZCuttingPos);
                await Task.Delay((int)ZAxisCuttingDelayTime.Parameter);
                //5.切割
                await ImpAbsMoveAsync(Cordinate, xTargetPos, yTargetPos);
               
                //6.停刀
                CuttingMotor.Value = false;
                //7.抬刀
                await AbsMoveAsync(ZAxis, ZWaitPos);
            }
            catch (Exception)
            {

                throw;
            }
        }

        private async Task CoordinateYCuttingAsync(PointSettingModel cuttingLength, double angle)
        {
            try
            {
                //0.计算坐标
                double xPos = Cordinate.XAxiPos;
                double yPos = Cordinate.YAxiPos + cuttingLength.Parameter;

                (double xTargetPos, double yTargetPos) = Components.Utilities.Utility.RotatePoint(xPos, yPos, angle);

                //1.先抬刀
                await AbsMoveAsync(ZAxis, ZWaitPos);
                //2.旋转刀向
                double knifeAngle = Components.Utilities.Utility.CalculateAngle(Cordinate.XAxiPos, Cordinate.YAxiPos, xTargetPos, yTargetPos);
                await AbsMoveAsync(UAxis, new PointSettingModel() { Parameter = knifeAngle });
                //3.启动刀
                CuttingMotor.Value = true;
                //4.下刀
                await AbsMoveAsync(ZAxis, ZCuttingPos); 
                await Task.Delay((int)ZAxisCuttingDelayTime.Parameter);
                //5.切割
                await ImpAbsMoveAsync(Cordinate, xTargetPos, yTargetPos);

                //6.停刀
                CuttingMotor.Value = false;
                //7.抬刀
                await AbsMoveAsync(ZAxis, ZWaitPos);
            }
            catch (Exception)
            {

                throw;
            }
        }


        private async Task CoordinateCuttingAsync(double originX,double originY,double destinationX,double destinationY)
        {
            try
            {
                //1.先抬刀
                await AbsMoveAsync(ZAxis, ZWaitPos);

                //2.旋转刀向

                double knifeAngle = Components.Utilities.Utility.CalculateAngle(originX, originY, destinationX, destinationY);

                await AbsMoveAsync(UAxis, new PointSettingModel() { Parameter = knifeAngle });
                //3.启动刀
                CuttingMotor.Value = true;
                //4.下刀
                await AbsMoveAsync(ZAxis, ZCuttingPos);
                await Task.Delay((int)ZAxisCuttingDelayTime.Parameter);
                //5.切割
                await ContiImpLineAbsMoveAsync(Cordinate, destinationX, destinationY);
                //6.停刀
                CuttingMotor.Value = false;
                //7.抬刀
                await AbsMoveAsync(ZAxis, ZWaitPos);
            }
            catch (Exception)
            {

                throw;
            }
        }

        private async Task AxisCuttingByAbsAsync(IMotion axis, PointSettingModel pos, double knifeAngle)
        {
            try
            {
                //1.先抬刀
                await AbsMoveAsync(ZAxis, ZWaitPos);
                //2.旋转刀向
                await AbsMoveAsync(UAxis, new PointSettingModel() { Parameter = knifeAngle });
                //3.启动刀
                CuttingMotor.Value = true;
                //4.下刀
                await AbsMoveAsync(ZAxis, ZCuttingPos);
                await Task.Delay((int)ZAxisCuttingDelayTime.Parameter);
                //5.切割
                await AbsMoveAsync(axis, pos);
                //6.停刀
                CuttingMotor.Value = false;
                //7.抬刀
                await AbsMoveAsync(ZAxis, ZWaitPos);
            }
            catch (Exception)
            {

                throw;
            }
        }


        /// <summary>
        /// 使用坐标系切割
        /// </summary>
        /// <param name="times">次数</param>
        /// <returns></returns>
        private async Task CoordCuttingRectangleAsync(int times=0)
        {
            try
            {
                //获取实体
                GetCADPahEntity();
            
                //1.获取点位的偏移值
                var points = GetCuttingPoints(DxfView.EntitiesWithPaths,_xVisionOffset,_yVisionOffset);

                if (points.Length<1)
                {
                    return;
                }

                double patternSpace = ProductModel.PatternSpace;

                (PointSettingModel xVisonPos, PointSettingModel yVisionPos) = GetPhotoPos();
                //2.去第一个切割点
                double firstPointX = points[0].X + xVisonPos.Parameter + patternSpace*times;
                double firstPointY = points[0].Y + yVisionPos.Parameter;

                double secondPointX = points[1].X + xVisonPos.Parameter + patternSpace * times;
                double secondPointY = points[1].Y + yVisionPos.Parameter;


                double thirdPointX = points[2].X + xVisonPos.Parameter + patternSpace * times;
                double thirdPointY = points[2].Y + yVisionPos.Parameter;


                double fourthPointX = points[3].X + xVisonPos.Parameter + patternSpace * times;
                double fourthPointY = points[3].Y + yVisionPos.Parameter;

                await MultiAbsMoveAsync(new IMotion[] {XAxis ,YAxis}, firstPointX, firstPointY);
                //3.先去切割
                await CoordinateCuttingAsync(firstPointX, firstPointY, secondPointX, secondPointY);

                await CoordinateCuttingAsync(secondPointX, secondPointY, thirdPointX, thirdPointY);

                await CoordinateCuttingAsync(thirdPointX, thirdPointY, fourthPointX, fourthPointY);

                await CoordinateCuttingAsync(fourthPointX, fourthPointY, firstPointX, firstPointY);



            }
            catch (Exception)
            {

                throw;
            }
        }


        #endregion


        #region Ulties


        public Vector2? GetVisionPoint(Dictionary<Type, List<PathEntityBase>> dic)
        {
            //获取实体
            GetCADPahEntity();

            if (dic.Count < 1)
            {
                dic = DxfView.EntitiesWithPaths;
            }
            Vector2? vector = null;
            
            foreach (var entityBases in dic.Values)
            {
                foreach (var enti in entityBases)
                {
                    if (enti.IsVisionPoint)
                    {
                         vector = new Vector2(enti.EndPoint.X, enti.EndPoint.Y);

                        break;
                    }
                    
                }


            }

            return vector;
        }


        public Vector2? GetFirstCuttingPoint(Dictionary<Type, List<PathEntityBase>> dic, Vector2? visionPoint)
        {
            //获取实体
            GetCADPahEntity();

            if (dic.Count < 1)
            {
                dic = DxfView.EntitiesWithPaths;
            }
            netDxf.Vector2? vector = null;
         

            foreach (var entityBases in dic.Values)
            {
                foreach (var enti in entityBases)
                {
                    if (enti.IsCuttingPoint && visionPoint!=null)
                    {
                        Vector2 vp = (Vector2)visionPoint;
                        //XY坐标和实际坐标相反，且y方向反了                                     
                        vector = new Vector2((enti.EndPoint.Y - vp.Y)*-1, enti.EndPoint.X - vp.X);

                        break;
                    }

                }


            }

            return vector;
        }

        public Vector2[] GetCuttingPoints(Dictionary<Type, List<PathEntityBase>> dic,double offsetX,double offsetY)
        {
            List<Vector2> points = new List<Vector2>();
            //1.先获取视觉配置位置
            var visionPoint = GetVisionPoint(dic);
            //2.获取第一个切割点位置
            var firstPoint = GetFirstCuttingPoint(dic, visionPoint);

            if (firstPoint!=null)
            {
                Vector2 firstCuttingPoint =(Vector2) firstPoint;
                Vector2 firstP= new Vector2(firstCuttingPoint.X + offsetX, firstCuttingPoint.Y + offsetY );
                points.Add(firstP);

                //获取产品切割的长度和宽度

                (double lenght,double width ) = GetCuttingLengthAndWidthByDouble();


                Vector2 secondP = new Vector2(firstP.X + lenght, firstP.Y);

                points.Add(secondP);


                Vector2 thridP = new Vector2(firstP.X + lenght, firstP.Y+width);

                points.Add(thridP);


                Vector2 fourthP = new Vector2(firstP.X, firstP.Y + width);

                points.Add(fourthP);
            }

           


            return points.ToArray();

        }
        public Vector2[]? GetPunchPoint(Dictionary<Type, List<PathEntityBase>> dic,Vector2? visionPoint)
        {
            //获取实体
            GetCADPahEntity();

            if (dic.Count < 1)
            {
                dic = DxfView.EntitiesWithPaths;
            }

            List<Vector2>? points = null;

            bool isFirstPunchPoint = true;

            points = new List<Vector2>();
            double lastX = 0;
            double lastY = 0;

            foreach (var entityBases in dic.Values)
            {
                foreach (var enti in entityBases)
                {
                    if (enti.IsPunchPoint)
                    {
                        
                        if (enti.MidPoint!=null)
                        {
                            Vector3 centerPint = (Vector3)enti.MidPoint;
                            double x = 0;
                            double y = 0;

                            


                            //第一个,从视觉点开始找偏移值


                            if (isFirstPunchPoint && visionPoint!=null)
                            {
                                isFirstPunchPoint = false;
                                Vector2 vp = (Vector2)visionPoint;

                                x = centerPint.X - vp.X;
                                y = centerPint.Y - vp.Y;

                                lastX = vp.X;
                                lastY = vp.Y;
                            }
                            else
                            {
                                x= centerPint.X - lastX;
                                y= centerPint.Y - lastY;

                                lastX = centerPint.X;
                                lastY = centerPint.Y;
                            }

                            

                            //XY坐标和实际坐标相反，且y方向反了
                            Vector2 vector = new Vector2(y*-1, x);

                            points.Add(vector);
                        }
                                          
                        
                    }

                }


            }

            return points?.ToArray();
        }


        public void GetCADPahEntity()
        {
            //1.获取最后的dxf选中文件名
            var fileName = ProductInfo.GetLastSelectFileName();

            if (fileName == null)
            {
                return;
            }

            //2.加载dxf文件
            LoadDxf(fileName);

            //3.设置实体的视觉点和打孔点

            SetDxfEntitiesPointStatus(fileName);


        }

      
        /// <summary>
        /// 载入Dxf
        /// </summary>
        /// <param name="fileName"></param>
        private void LoadDxf(string fileName)
        {

            string filePath = Paths.DxfSavePaths;

            string _fileName = fileName;

            // 构建目标文件路径
            string targetFilePath = System.IO.Path.Combine(filePath, fileName + ".dxf");

            if (!File.Exists(targetFilePath))
            {
                targetFilePath = System.IO.Path.Combine(filePath, fileName + ".dwg");
            }

            if (File.Exists(targetFilePath))
            {
                
                DxfReader dxfReader = new DxfReader();
                dxfReader.ReadFromFile(targetFilePath);
                var dxfEntities = dxfReader.entitiesWithPaths;

                EntitiesWithPaths = dxfEntities;
                            
            }
            else
            {
                MessageBox.Show("文件获取失败");
            }
        }


        private void SetDxfEntitiesPointStatus(string fileName)
        {
            var models = ReadConfigData.GetParaConfigs<DxfCharacterModel>(Paths.DxfConfigPaths);
            if (models != null)
            {
                foreach (var model in models)
                {

                    if (model.ControlName == fileName)
                    {
                        if (model?.PunchesHandles?.Length > 0)
                        {
                            foreach (var p in model.PunchesHandles)
                            {
                                Dxf.Utils.Utility.SetEntityPunchPoint(EntitiesWithPaths, p, true);
                            }
                        }

                        if (model?.VisionHandles?.Length > 0)
                        {
                            foreach (var p in model.VisionHandles)
                            {
                                Dxf.Utils.Utility.SetEntityVisionPoint(EntitiesWithPaths, p, true);
                            }
                        }

                        if (model?.CuttingHandles?.Length > 0)
                        {
                            foreach (var p in model.CuttingHandles)
                            {
                                Dxf.Utils.Utility.SetEntityCuttingPoint(EntitiesWithPaths, p, true);
                            }
                        }

                    }
                }
            }
        }


        private  (PointSettingModel, PointSettingModel, PointSettingModel, PointSettingModel, PointSettingModel) GetCuttingLengthAndWidth()
        {
          
            PointSettingModel pXCuttingLenght = new PointSettingModel() { Parameter = ProductModel.CuttingLength + ProductModel.KnifeCompensate };
            PointSettingModel pYCuttingWidth = new PointSettingModel() { Parameter = ProductModel.CuttingWidth + ProductModel.KnifeCompensate };
            PointSettingModel nXCuttingLenght = new PointSettingModel() { Parameter = (ProductModel.CuttingLength + ProductModel.KnifeCompensate) * -1 };
            PointSettingModel nYCuttingWidth = new PointSettingModel() { Parameter = (ProductModel.CuttingWidth + ProductModel.KnifeCompensate) * -1 };

            PointSettingModel pSpace = new PointSettingModel() { Parameter = ProductModel.Space };

            return (pXCuttingLenght, pYCuttingWidth, nXCuttingLenght, nYCuttingWidth, pSpace);
        }


        private double GetPatternSpace()
        {
          
            return ProductModel.PatternSpace;
        }


        private  (PointSettingModel, PointSettingModel) GetPhotoPos()
        {
            
            PointSettingModel photoXPos = new PointSettingModel() { Parameter = ProductModel.XAxisPhotoPos };
            PointSettingModel photoYPos = new PointSettingModel() { Parameter = ProductModel.YAxisPhotoPos };


            return (photoXPos, photoYPos);
        }


        private  (double, double) GetCuttingLengthAndWidthByDouble()
        {
           
            return (ProductModel.CuttingLength + ProductModel.KnifeCompensate, ProductModel.CuttingWidth + ProductModel.KnifeCompensate);
        }

        #endregion







    }
}
